package lib

import (
	"GameServer/Common/data"
	"GameServer/Common/utils"
	"GameServer/Game/errors"
	"GameServer/Game/m"
	"fmt"
	"math/rand"
	"time"
)

// 洗牌算法1
func Shuffle_A(cards []int64) (result []int64) {
	rand.Seed(time.Now().UTC().UnixNano())
	result = make([]int64, 0)
	for _, value := range cards {
		result = append(result, value)
	}
	for i := len(cards); i > 0; i-- {
		last := i - 1
		idx := rand.Intn(i)
		result[last], result[idx] = result[idx], result[last]
	}
	return result
}

// 获取章节对应的基础卡组
func GetBaseCardDeck(lockBlockTid int64) (baseDeck []int64, err error) {
	//fmt.Println("获取章节对应的基础卡组")
	baseDeck = make([]int64, 0)
	tpl, ok := data.Get("CardDecks", uint64(lockBlockTid))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到基础卡库，tid:%d", lockBlockTid))
		return nil, err
	}
	cardDeckConfig := tpl.(data.CardDeck)
	deck := cardDeckConfig.Deck
	for _, kv := range deck {
		tid := kv.Key
		num := kv.Value
		for i := 0; i < int(num); i++ {
			baseDeck = append(baseDeck, int64(tid))
			//fmt.Println(tid)
		}
	}
	return
}

func GetNewCardDeck(lockBlockTid int64, extraCard map[int64]int64) (result []int64) {
	result, err := GetBaseCardDeck(lockBlockTid)
	if err != nil {
		// 找不到对应章节的卡组，保底使用第一章节的卡组
		result, _ = GetBaseCardDeck(1)
	}
	// 添加额外卡组的卡，到卡组中
	if extraCard != nil && len(extraCard) > 0 {
		for tid, num := range extraCard {
			for i := 0; i < int(num); i++ {
				result = append(result, tid)
			}
		}
	}
	// 洗牌后返回
	result2 := Shuffle_A(result)
	return result2
}

// 给玩家卡组增加卡牌
func AddCardIndDeck(u *m.User, cardTid int64) {
	cardGame := u.GetCardGame()
	cardDeck := cardGame.GetCardDeck(u.Pos.LockBlockTid)
	if cardDeck.ExtraCard == nil {
		cardDeck.ExtraCard = make(map[int64]int64, 0)
	}
	// 卡牌有效性检测
	_, ok := data.Get("Cards", uint64(cardTid))
	if ok {
		orgNum := int64(0)
		_, find := cardDeck.ExtraCard[cardTid]
		if find {
			orgNum = cardDeck.ExtraCard[cardTid]
		}
		cardDeck.ExtraCard[cardTid] = orgNum + 1
	} else {
		//err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到用户卡牌配置信息，tid:%d", cardTid))
	}
	// 存盘
	cardGame.CardDeck = cardDeck
	cardGame.Update(cardGame)
	return
}

// 给玩家卡组增加卡牌 -- 多人战斗
func AddCardIndDeck_MulCombat(u *m.User, cardTid int64) {
	cardGame := u.GetCardGameMulCombat()
	cardDeck := cardGame.GetCardDeck(u.Pos.LockBlockTid)
	if cardDeck.ExtraCard == nil {
		cardDeck.ExtraCard = make(map[int64]int64, 0)
	}
	// 卡牌有效性检测
	_, ok := data.Get("Cards", uint64(cardTid))
	if ok {
		orgNum := int64(0)
		_, find := cardDeck.ExtraCard[cardTid]
		if find {
			orgNum = cardDeck.ExtraCard[cardTid]
		}
		cardDeck.ExtraCard[cardTid] = orgNum + 1
	} else {
		//err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到用户卡牌配置信息，tid:%d", cardTid))
	}
	// 存盘
	cardGame.CardDeck = cardDeck
	cardGame.Update(cardGame)
	return
}

// 技能是否为怪物原生的技能
func IsMonsterOrgSkill(skillTid uint64, monsterConfig data.CardMonster) (isOrg bool) {
	isOrg = false
	skillLst := monsterConfig.SkillIds
	if skillLst != nil && len(skillLst) > 0 {
		for _, value := range skillLst {
			if skillTid == value {
				isOrg = true
				break
			}
		}
	}
	return isOrg
}

// 伤害属性转换
func CombatSpAtkTypFormat(typLst []uint64) (SpAtkTyp map[int64]int64) {
	if typLst == nil || len(typLst) == 0 {
		return nil
	} else {
		SpAtkTyp = make(map[int64]int64, 0)
		for _, val := range typLst {
			SpAtkTyp[int64(val)] = 1
		}
		return SpAtkTyp
	}
}

// 放弃魔法书
func MaigcBookAbandon(cardGame *m.CardGame, gridId int64) {
	magicBook := &m.MagicBook{
		Typ:        0, // 魔法书类型
		Status:     0, // 设置为没记录
		GridId:     gridId,
		ResetCount: 0,
		CardLst:    make(map[int64]int64, 0),
	}
	cardGame.MagicBook = magicBook
	cardGame.Update(cardGame)
	return
}

// 选择魔法书结果
func MagicBookAccept(u *m.User, cardGame *m.CardGame, cardTid int64, gridId int64) (err error) {
	magicBook := cardGame.GetMagicBookInfo()
	_, find := magicBook.CardLst[cardTid]
	if find == false {
		errMsg := fmt.Sprintf("没有该ID的卡牌 %d", cardTid)
		fmt.Println(errMsg)
		err = errors.NewErrcode(data.Errcode.ServerErr, errMsg)
		return err
	}
	AddCardIndDeck(u, cardTid)
	// magicBook.Typ = 0
	magicBook.Status = 0 // 设置为没记录
	magicBook.ResetCount = 0
	magicBook.GridId = gridId
	cardGame.MagicBook = magicBook
	cardGame.Update(cardGame)
	return nil
}

// 魔法书重置
func MagicBookReset(u *m.User, cardGame *m.CardGame, gridId int64) (err error) {
	magicBook := cardGame.GetMagicBookInfo()
	// 检查是否超过最大重置次数上限
	if magicBook.ResetCount > 1 {
		err = errors.NewErrcode(data.Errcode.ServerErr, "超过重置次数")
		return
	}
	// 检查格子是否有魔法书
	gridInfo, _ := u.GetGrid(gridId)
	if gridInfo.Goods == nil {
		err = errors.NewErrcode(data.Errcode.ServerErr, fmt.Sprintf("格子没有道具,gid:%d", gridId))
		return
	}
	tpl, ok := data.Get("Goods", uint64(gridInfo.Goods.Tid))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没找到道具配置,id:%d", gridInfo.Goods.Tid))
		return
	}
	goodsConfig := tpl.(data.Good)
	magicBookTyp := int64(goodsConfig.Type)
	if goodsConfig.Category != 6 {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("格子道具不是魔法书,id:%d", gridInfo.Goods.Tid))
		return
	}
	if magicBookTyp != data.GoodsTypeEnum.MagicBookRed &&
		magicBookTyp != data.GoodsTypeEnum.MagicBookBlue &&
		magicBookTyp != data.GoodsTypeEnum.MagicBookPurple {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("格子道具不是魔法书,id:%d", gridInfo.Goods.Tid))
		return
	}
	// 根据魔法书类型，塞卡牌
	lockBlockTid := u.Pos.LockBlockTid
	tpl, ok = data.Get("MagicBookConfigs", uint64(lockBlockTid))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到MagicBook配置,id:%d", lockBlockTid))
		return
	}
	mbConifg := tpl.(data.MagicBookConfig)
	weightKvs := make([]data.WeightKV, 0)
	switch magicBookTyp {
	case data.GoodsTypeEnum.MagicBookRed:
		for _, kv := range mbConifg.RedDeck {
			weightKvs = append(weightKvs, data.WeightKV{
				Weight: kv.Key,   // 权重
				Key:    kv.Value, // 卡牌Tid
			})
		}
	case data.GoodsTypeEnum.MagicBookBlue:
		for _, kv := range mbConifg.BlueDeck {
			weightKvs = append(weightKvs, data.WeightKV{
				Weight: kv.Key,   // 权重
				Key:    kv.Value, // 卡牌Tid
			})
		}
	case data.GoodsTypeEnum.MagicBookPurple:
		for _, kv := range mbConifg.PurpleDeck {
			weightKvs = append(weightKvs, data.WeightKV{
				Weight: kv.Key,   // 权重
				Key:    kv.Value, // 卡牌Tid
			})
		}
	default:
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到MagicBook类型,typ:%d", magicBookTyp))
		return
	}
	// 得到第一个随机卡片
	one := utils.RandomWeightKV(weightKvs)
	// 排除第一张卡，得到第二个随机卡片
	weightKvs_two := make([]data.WeightKV, 0)
	for _, wkv := range weightKvs {
		if wkv.Key == one.Key {
			continue
		} else {
			weightKvs_two = append(weightKvs_two, wkv)
		}
	}
	two := utils.RandomWeightKV(weightKvs_two)
	// 赋值
	orgResetCount := magicBook.ResetCount
	magicBook = &m.MagicBook{
		Typ:        magicBookTyp, // 魔法书类型
		Status:     1,            // 设置为有记录
		GridId:     gridId,
		ResetCount: orgResetCount + 1, // 累计重置次数
		CardLst:    make(map[int64]int64, 0),
	}
	magicBook.CardLst[int64(one.Key)] = 1
	magicBook.CardLst[int64(two.Key)] = 1
	cardGame.MagicBook = magicBook
	cardGame.Update(cardGame)
	return
}

// 魔法书获得
func MagicBookGet(u *m.User, cardGame *m.CardGame, gridId int64) (err error) {
	// 检查格子是否有魔法书
	gridInfo, _ := u.GetGrid(gridId)
	if gridInfo.Goods == nil {
		err = errors.NewErrcode(data.Errcode.ServerErr, fmt.Sprintf("格子没有道具,gid:%d", gridId))
		return
	}
	tpl, ok := data.Get("Goods", uint64(gridInfo.Goods.Tid))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没找到道具配置,id:%d", gridInfo.Goods.Tid))
		return
	}
	goodsConfig := tpl.(data.Good)
	magicBookTyp := int64(goodsConfig.Type)
	if goodsConfig.Category != 6 {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("格子道具不是魔法书,id:%d", gridInfo.Goods.Tid))
		return
	}
	if magicBookTyp != data.GoodsTypeEnum.MagicBookRed &&
		magicBookTyp != data.GoodsTypeEnum.MagicBookBlue &&
		magicBookTyp != data.GoodsTypeEnum.MagicBookPurple {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("格子道具不是魔法书,id:%d", gridInfo.Goods.Tid))
		return
	}
	// 已经有记录，直接返回
	if cardGame.MagicBook != nil &&
		cardGame.MagicBook.Status == 1 &&
		cardGame.MagicBook.CardLst != nil &&
		len(cardGame.MagicBook.CardLst) > 0 {
		return nil
	}
	// 根据魔法书类型，塞卡牌
	lockBlockTid := u.Pos.LockBlockTid
	tpl, ok = data.Get("MagicBookConfigs", uint64(lockBlockTid))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到MagicBook配置,id:%d", lockBlockTid))
		return
	}
	mbConifg := tpl.(data.MagicBookConfig)
	weightKvs := make([]data.WeightKV, 0)
	switch magicBookTyp {
	case data.GoodsTypeEnum.MagicBookRed:
		for _, kv := range mbConifg.RedDeck {
			weightKvs = append(weightKvs, data.WeightKV{
				Weight: kv.Key,   // 权重
				Key:    kv.Value, // 卡牌Tid
			})
		}
	case data.GoodsTypeEnum.MagicBookBlue:
		for _, kv := range mbConifg.BlueDeck {
			weightKvs = append(weightKvs, data.WeightKV{
				Weight: kv.Key,   // 权重
				Key:    kv.Value, // 卡牌Tid
			})
		}
	case data.GoodsTypeEnum.MagicBookPurple:
		for _, kv := range mbConifg.PurpleDeck {
			weightKvs = append(weightKvs, data.WeightKV{
				Weight: kv.Key,   // 权重
				Key:    kv.Value, // 卡牌Tid
			})
		}
	default:
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到MagicBook类型,typ:%d", magicBookTyp))
		return
	}
	// 得到第一个随机卡片
	one := utils.RandomWeightKV(weightKvs)
	// 排除第一张卡，得到第二个随机卡片
	weightKvs_two := make([]data.WeightKV, 0)
	for _, wkv := range weightKvs {
		if wkv.Key == one.Key {
			continue
		} else {
			weightKvs_two = append(weightKvs_two, wkv)
		}
	}
	two := utils.RandomWeightKV(weightKvs_two)
	// 赋值
	magicBook := &m.MagicBook{
		Typ:        magicBookTyp, // 魔法书类型
		Status:     1,            // 设置为有记录
		GridId:     gridId,       // 记录格子ID
		ResetCount: 0,            // 累计重置次数
		CardLst:    make(map[int64]int64, 0),
	}
	magicBook.CardLst[int64(one.Key)] = 1
	magicBook.CardLst[int64(two.Key)] = 1
	cardGame.MagicBook = magicBook
	cardGame.Update(cardGame)
	return
}
